package com.acme.logginglab.mylogger;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.Marker;

import com.acme.logginglab.appenders.Appender;
import com.acme.logginglab.appenders.AsyncFileAppender;
import com.acme.logginglab.appenders.ConsoleAppender;

public class MyLogger implements Logger {
	private final String propertyFileName = "/mylogger.properties";
	private final String name;
	private Appender appender;
	private LogLevel level;

	public MyLogger(String name) {
		this(LogLevel.INFO, name);
	}

	public MyLogger(LogLevel l, String name) {
		this.name = name;
		level = l;
		InputStream in = getClass().getResourceAsStream(propertyFileName);
		Properties props = new Properties();
		try {
			props.load(in);
			String appenderType = props.getProperty("mylogger.appender");
			if ("file".equals(appenderType)) {
				appender = AsyncFileAppender.getInstance();
			} else {
				appender = ConsoleAppender.getInstance();
			}
			String levelprop = props.getProperty("mylogger.level");
			if (levelprop == null) {
				level = LogLevel.INFO;
			} else {
				level = LogLevel.valueOf(levelprop);
			}
		} catch (IOException e) {
			appender = ConsoleAppender.getInstance();
		}
	}

	public void setLevel(LogLevel l) {
		level = l;
	}

	public String getName() {
		return name;
	}

	public boolean isDebugEnabled() {
		return level.ordinal() <= LogLevel.DEBUG.ordinal();
	}

	public void debug(String msg) {
		if (isDebugEnabled())
			appender.append(LogLevel.DEBUG, msg);
	}

	public void debug(String format, Object arg) {
		if (isDebugEnabled()) {
			String msg = format.replaceFirst("\\{\\}", arg.toString());
			appender.append(LogLevel.DEBUG, msg);
		}
	}

	public void debug(String format, Object arg1, Object arg2) {
		if (isDebugEnabled()) {
			String msg = format.replaceFirst("\\{\\}", arg1.toString());
			msg = msg.replaceFirst("\\{\\}", arg2.toString());

			appender.append(LogLevel.DEBUG, msg);
		}
	}

	public void debug(String format, Object... arguments) {
		if (isDebugEnabled()) {
			String msg = format;

			for (Object arg : arguments) {
				msg = msg.replaceFirst("\\{\\}", arg.toString());
			}

			appender.append(LogLevel.DEBUG, msg);
		}
	}

	public void debug(String msg, Throwable t) {
		if (isDebugEnabled())
			appender.append(LogLevel.DEBUG, t.getMessage());
	}

	public boolean isDebugEnabled(Marker marker) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void debug(Marker marker, String msg) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void debug(Marker marker, String format, Object arg) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void debug(Marker marker, String format, Object arg1, Object arg2) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void debug(Marker marker, String format, Object... arguments) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void debug(Marker marker, String msg, Throwable t) {
		throw new UnsupportedOperationException("Not implemented");

	}

	public boolean isInfoEnabled() {
		return level.ordinal() <= LogLevel.INFO.ordinal();
	}

	public void info(String msg) {
		if (isInfoEnabled())
			appender.append(LogLevel.INFO, msg);
	}

	public void info(String format, Object arg) {
		if (isInfoEnabled()) {
			String msg = format;
			msg = msg.replaceFirst("\\{\\}", arg.toString());

			appender.append(LogLevel.INFO, msg);
		}
	}

	public void info(String format, Object arg1, Object arg2) {
		if (isInfoEnabled()) {
			String msg = format;

			msg = msg.replaceFirst("\\{\\}", arg1.toString());
			msg = msg.replaceFirst("\\{\\}", arg2.toString());

			appender.append(LogLevel.INFO, msg);
		}

	}

	public void info(String format, Object... arguments) {
		if (isInfoEnabled()) {
			String msg = format;

			for (Object arg : arguments) {
				msg = msg.replaceFirst("\\{\\}", arg.toString());
			}

			appender.append(LogLevel.INFO, msg);
		}
	}

	public void info(String msg, Throwable t) {
		if (isInfoEnabled()) {
			appender.append(LogLevel.INFO, t.getMessage());
		}
	}

	public boolean isInfoEnabled(Marker marker) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void info(Marker marker, String msg) {
		throw new UnsupportedOperationException("Not implemented");

	}

	public void info(Marker marker, String format, Object arg) {
		throw new UnsupportedOperationException("Not implemented");

	}

	public void info(Marker marker, String format, Object arg1, Object arg2) {
		throw new UnsupportedOperationException("Not implemented");

	}

	public void info(Marker marker, String format, Object... arguments) {
		throw new UnsupportedOperationException("Not implemented");

	}

	public void info(Marker marker, String msg, Throwable t) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public boolean isWarnEnabled() {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void warn(String msg) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void warn(String format, Object arg) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void warn(String format, Object... arguments) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void warn(String format, Object arg1, Object arg2) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void warn(String msg, Throwable t) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public boolean isWarnEnabled(Marker marker) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void warn(Marker marker, String msg) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void warn(Marker marker, String format, Object arg) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void warn(Marker marker, String format, Object arg1, Object arg2) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void warn(Marker marker, String format, Object... arguments) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void warn(Marker marker, String msg, Throwable t) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public boolean isErrorEnabled() {
		return level.ordinal() <= LogLevel.ERROR.ordinal();
	}

	public void error(String msg) {
		if (isErrorEnabled()) {
			appender.append(LogLevel.ERROR, msg);
		}
	}

	public void error(String format, Object arg) {
		if (isErrorEnabled()) {
			String msg = format;

			msg = msg.replaceFirst("\\{\\}", arg.toString());

			appender.append(LogLevel.ERROR, msg);
		}
	}

	public void error(String format, Object arg1, Object arg2) {
		if (isErrorEnabled()) {
			String msg = format;

			msg = msg.replaceFirst("\\{\\}", arg1.toString());
			msg = msg.replaceFirst("\\{\\}", arg2.toString());

			appender.append(LogLevel.ERROR, msg);
		}
	}

	public void error(String format, Object... arguments) {
		if (isErrorEnabled()) {
			String msg = format;

			for (Object arg : arguments) {
				msg = msg.replaceFirst("\\{\\}", arg.toString());
			}

			appender.append(LogLevel.ERROR, msg);
		}
	}

	public void error(String msg, Throwable t) {
		if (isErrorEnabled()) {
			appender.append(LogLevel.ERROR, t.getMessage());
		}
	}

	public boolean isErrorEnabled(Marker marker) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void error(Marker marker, String msg) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void error(Marker marker, String format, Object arg) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void error(Marker marker, String format, Object arg1, Object arg2) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void error(Marker marker, String format, Object... arguments) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void error(Marker marker, String msg, Throwable t) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public boolean isTraceEnabled() {
		return false;
	}

	public void trace(String msg) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void trace(String format, Object arg) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void trace(String format, Object arg1, Object arg2) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void trace(String format, Object... arguments) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void trace(String msg, Throwable t) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public boolean isTraceEnabled(Marker marker) {
		return false;
	}

	public void trace(Marker marker, String msg) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void trace(Marker marker, String format, Object arg) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void trace(Marker marker, String format, Object arg1, Object arg2) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void trace(Marker marker, String format, Object... argArray) {
		throw new UnsupportedOperationException("Not implemented");
	}

	public void trace(Marker marker, String msg, Throwable t) {
		throw new UnsupportedOperationException("Not implemented");
	}
}